# -*- coding: utf-8 -*-
# @Time: 2022/9/12 12:04
# @File: image_tool.py

import os
import win32api
import win32con
from PIL import Image
from random import choice
from random import shuffle


def image_to_animation_files(image_path):
    """
    将图片切割成多个动画文件，新建文件夹保存下来
    :param image_path: 图片路径
    :return: 动画文件夹的路径
    """
    # 打开读取图片
    image_data = Image.open(image_path)
    width, height = image_data.size

    # 解析图片路径和名称中的信息，名称样例：bird_red_fly_1x8.png
    folder, image_name = os.path.split(image_path)
    full_name, suffix = image_name.split(".")
    *name, size = full_name.split("_")
    row, col = (int(i) for i in size.split("x"))

    # 判断并新建文件夹
    new_name = "_".join(name)
    new_folder = os.path.join(folder, new_name)
    if not os.path.exists(new_folder):
        os.mkdir(new_folder)

    per_width, per_height = width / col, height / row
    index = 0
    for x in range(row):
        for y in range(col):
            # 获取切割部分的左上角指标
            left, top = y * per_width, x * per_height
            part_image = image_data.crop(  # 图片切割
                (left, top, left + per_width, top + per_height))
            part_image_name = f"{new_name}{index}.{suffix}"
            part_image.save(os.path.join(new_folder, part_image_name))
            index += 1

    return new_folder


def get_image_pixel(image_path, location):
    """
    获取图片某坐标的RGB像素值
    :param image_path: 图片路径
    :param location: 像素坐标
    :return: RGB像素值
    """
    image_data = Image.open(image_path).convert("RGB")
    return image_data.getpixel(location)


def invert_picture(image_path, vertical=True):
    """
    对图片进行水平或垂直反转
    :param image_path: 图片路径
    :param vertical: 垂直反转，否则水平反转
    :return:
    """
    image_data = Image.open(image_path)
    if vertical:
        new_image_data = image_data.transpose(Image.FLIP_TOP_BOTTOM)
    else:
        new_image_data = image_data.transpose(Image.FLIP_LEFT_RIGHT)
    new_image_data.save(image_path)


def image_merge(
        file_dir, save_file="merge_image.jpg", zoom=1, order=True, ploy="min"):
    """
    将多张小图片合并为一张大图片
    :param file_dir: 小图片所在的文件夹
    :param save_file: 大图片的保存路径和名称
    :param zoom: 大图片的分辨率相对屏幕的缩放比，默认为1
    :param order: 是否保存小图片的原有顺序
    :param ploy: 每行的高度策略，默认为min，可选策略：
                 min：每行中最低的高度定义整行的高度
                 max：每行中最高的高度定义整行的高度
                 avg：每行中的平均高度定义整行的高度
    :return:
    """
    sw = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) * zoom
    sh = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) * zoom
    image = Image.new("RGB", (sw, sh))
    x = y = 0
    file_list = os.listdir(file_dir)
    if not order:
        shuffle(file_list)  # 打乱原有图片顺序
    min_h = sh
    max_h = 0
    all_h = 0
    col_n = 0
    for f in file_list:
        data = Image.open(os.path.join(file_dir, f))
        image.paste(data, (x, y))
        w, h = data.size
        x += w
        min_h = min(min_h, h)
        max_h = max(max_h, h)
        all_h += h
        col_n += 1
        if x >= sw:
            # 不同的高度策略
            if ploy == "min":
                y += min_h
                min_h = sh
            elif ploy == "max":
                y += max_h
                max_h = 0
            elif ploy == "avg":
                y += (all_h // col_n)
                all_h = 0
                col_n = 0
            x = 0
        if y >= sh:
            break
    # 如果所有的小图片无法合成需要分辨率的大图片，将用随机的小图片拼接剩下的部分
    while y < sh:
        data = Image.open(
            os.path.join(file_dir, choice(file_list)))
        image.paste(data, (x, y))
        w, h = data.size
        x += w
        if x >= sw:
            # 不同的高度策略
            if ploy == "min":
                y += min_h
                min_h = sh
            elif ploy == "max":
                y += max_h
                max_h = 0
            elif ploy == "avg":
                y += (all_h // col_n)
                all_h = 0
                col_n = 0
            x = 0
    image.save(save_file)


if __name__ == "__main__":
    image_merge(r"C:\Users\XYe\Downloads\番号图片", zoom=4, order=False,
                ploy="min")
